package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.serivce.IStrategySearchService;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSourceBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategySearchServiceImpl implements IStrategySearchService {

    @Autowired
    private StrategyTemplateRepository repository;

    @Override
    public void save(StrategyTemplate template) {
        repository.save(template);
    }

    //主题推荐
    @Override
    public List<Map<String, Object>> queryThemeCommend() {
        List<Map<String,Object>> data = new ArrayList<>();

        List<StatisVO> themes = this.statisGroup("themeId","themeName","themeGroup",null);

        //======取前面10个========================
        if (themes.size() > 10){
            themes = themes.subList(0, 10); //SubList();
        }


        //  ---------------遍历List<StatisVO> 得到每个主题关联目的地集合----------------

        Map<String,Object> map = null;
        for (StatisVO theme : themes) {

            map = new HashMap<>();

            //左边为主题对象
            map.put("theme",theme);
            //目的地集合
            List<StatisVO> dests = this.getDestByThemeId(theme.getId());
            //右边主题关联目的地集合
            map.put("dests",dests);

            data.add(map);
        }

        return data;
    }


    // 通过主题id查询目的地的id name
    private List<StatisVO> getDestByThemeId(Long themeId) {

        //===3:去除重复目的地========================
        //jpa 的语法规范: findBy属性名
        List<StrategyTemplate>  list = repository.findByThemeId(themeId);

        List<StatisVO> dests = new ArrayList<>();
        //已经存在目的地名
        List<String> names = new ArrayList<>();
        for (StrategyTemplate template : list) {
            if(!names.contains(template.getDestName())){
                StatisVO vo = new StatisVO();
                vo.setId(template.getDestId());
                vo.setName(template.getDestName());
                dests.add(vo);
                names.add(template.getDestName());
            }
        }
        return dests;
    }

    //抽取方法
    public List<StatisVO> statisGroup(String idFeild, String nameFeild, String groupName, BoolQueryBuilder query){

        //执行es DSL分组查询语句得到List<StatisVO> id name count
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();

        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id"); //字段的自定义分组名
        idSource.field(idFeild);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name"); //字段的自定义分组名
        nameSource.field(nameFeild);
        sources.add(idSource);
        sources.add(nameSource);

        //分组集合对象:参数1: 分组查询名称, 参数2:分组列的集合:themeId themeName
        CompositeAggregationBuilder aggBuilder = new CompositeAggregationBuilder(groupName, sources);

        //DSL拼接对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(aggBuilder);
        builder.withPageable(PageRequest.of(0,1));

        //过滤条件
        if(query != null){
            builder.withQuery(query);
        }

        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        CompositeAggregation themeGroup = page.getAggregations().get(groupName);

        List<? extends CompositeAggregation.Bucket> buckets = themeGroup.getBuckets();

        List<StatisVO> themes = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : buckets) {
            Long id = Long.parseLong(bucket.getKey().get("id").toString());//拿到id的值,先转string再转Long
            String name = bucket.getKey().get("name").toString();
            Long count = bucket.getDocCount();

            StatisVO vo = new StatisVO(id,name,count);
            themes.add(vo);
        }

        //====需要排行, 按照攻略个数排行=====
        Collections.sort(themes, new Comparator<StatisVO>() {
            //22对象比较, 根据返回值决定在list集合顺序
            //返回 大于 0 : 大于
            //返回 小于 0 : 小于
            //返回 等于 0 : 等于
            public int compare(StatisVO o1, StatisVO o2) {
                //Long ret = o1.getCount() - o2.getCount(); //正序
                Long ret = o2.getCount() - o1.getCount();  //倒序
                return ret.intValue();
            }
        });

        return themes;
    }

    //主题攻略条件列表
    @Override
    public List<StatisVO> queryConditionThemes() {

        return this.statisGroup("themeId","themeName","themeGroup",null);
    }

    //国内
    @Override
    public List<StatisVO> queryConditionProvinces() {

        return this.statisGroup("provinceId","provinceName","provinceGroup",null);
    }

    //国外
    @Override
    public List<StatisVO> queryConditionCountries() {
        BoolQueryBuilder query = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery("countryId", 1));
        return this.statisGroup("countryId","countryName","countryGroup",query);
    }

    //分页查询
    @Override
    public Page query(StrategySearchQuery qo) {
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_ABROAD) {
            //国外
            builder.must(QueryBuilders.termQuery("countryId",qo.getTypeValue()));
        }else if (qo.getType() == StrategySearchQuery.CONDITION_TYPE_CHINA){
            //国内
            builder.must(QueryBuilders.termQuery("provinceId",qo.getTypeValue()));
        }else if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_THEME){
            //主题
            builder.must(QueryBuilders.termQuery("themeId",qo.getTypeValue()));
        }
        return repository.search(builder,qo.getPageable());
    }

    @Override
    public List<StrategyTemplate> findByDestName(String name) {
        return repository.findByDestName(name);
    }


}
